/************************************************************************
 * @file LoggerService.cpp
 * @author Ian Chen
 * @version 1.0
 * 
 * @section LICENSE
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 3 of
 * the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
 * General Public License for more details at
 * http://www.gnu.org/licenses/lgpl.html
 ************************************************************************/
#include <QCoreApplication>
#include <QDir>
#include <QFile>
#include <QStringBuilder>
#include <QString>


#include <plugin/service/LoggerService.h>
#include <plugin/plugin/AbstractPlugin.h>
#include <plugin/command/AbstractLogCommand.h>

namespace antu
{
namespace plugin
{
const char* LoggerService::LOG_COMMAND_NAME  = "log";
const char* LoggerService::LOG_PARAM_TYPE    = "LOG_PARAM_TYPE";
const char* LoggerService::LOG_PARAM_CLASS   = "LOG_PARAM_CLASS";
const char* LoggerService::LOG_PARAM_METHOD  = "LOG_PARAM_METHOD";
const char* LoggerService::LOG_PARAM_MESSAGE = "LOG_PARAM_MESSAGE";
const char* LoggerService::LOGGER_SERVICE    = "log";
const char* LoggerService::LOG_PARAM_FILE    = "FILE";
const char* LoggerService::LOG_PARAM_LINE    = "LINE";
const char* LoggerService::LOG_LEVEL_DEBUG   = "debug";
const char* LoggerService::LOG_LEVEL_INFO    = "info";
const char* LoggerService::LOG_LEVEL_ERROR   = "error";
const char* LoggerService::LOG_LEVEL_WARN    = "warn";
const char* LoggerService::LOG_LEVEL_FATAL   = "fatal";

LoggerService::LoggerService(const QString& level /* = QString("debug")*/)
    : AbstractService(LoggerService::LOGGER_SERVICE),
      m_pLogCommand(nullptr),
      m_sLogLevel(level)
{
}

void LoggerService::debug( const QString& fileName, int line, const QString& className, const QString& methodName, const QString& message )
{
    if (this->m_pLogCommand != nullptr)
    {
        this->m_pLogCommand->debug(fileName, line, className, methodName, message);
    }
}

void LoggerService::info( const QString& fileName, int line, const QString& className, const QString& methodName, const QString& message )
{
    if (this->m_pLogCommand != nullptr)
    {
        this->m_pLogCommand->info(fileName, line, className, methodName, message);
    }
}

void LoggerService::warn( const QString& fileName, int line, const QString& className, const QString& methodName, const QString& message )
{
    if (this->m_pLogCommand != nullptr)
    {
        this->m_pLogCommand->warn(fileName, line, className, methodName, message);
    }
}

void LoggerService::error( const QString& fileName, int line, const QString& className, const QString& methodName, const QString& message )
{
    if (this->m_pLogCommand != nullptr)
    {
        this->m_pLogCommand->error(fileName, line, className, methodName, message);
    }
}

void LoggerService::fatal( const QString& fileName, int line, const QString& className, const QString& methodName, const QString& message )
{
    if (this->m_pLogCommand != nullptr)
    {
        this->m_pLogCommand->fatal(fileName, line, className, methodName, message);
    }
}

void LoggerService::log( LogType type, const QString& fileName, int line, const QString& className, const QString& methodName, const QString& message )
{
    switch (type)
    {
    case LVL_INFO:
        this->info(fileName, line, className, methodName, message);
        break;
    case LVL_DEBUG:
        this->debug(fileName, line, className, methodName, message);
        break;
    case LVL_ERROR:
        this->error(fileName, line, className, methodName, message);
        break;
    case LVL_WARNING:
        this->warn(fileName, line, className, methodName, message);
        break;
    case LVL_FATAL:
        this->fatal(fileName, line, className, methodName, message);
        break;
    default:
        this->debug(fileName, line, className, methodName, message);
        break;
    }
}

void LoggerService::setLogLevel( const QString& logLevel )
{
    if (this->m_pLogCommand != nullptr)
    {
        if (QString::compare(logLevel, LoggerService::LOG_LEVEL_DEBUG, Qt::CaseInsensitive) == 0)
        {
            this->m_pLogCommand->setLogLevel(LVL_DEBUG);
        }
        else if (QString::compare(logLevel, LoggerService::LOG_LEVEL_INFO, Qt::CaseInsensitive) == 0)
        {
            this->m_pLogCommand->setLogLevel(LVL_INFO);
        }
        else if (QString::compare(logLevel, LoggerService::LOG_LEVEL_WARN, Qt::CaseInsensitive) == 0)
        {
            this->m_pLogCommand->setLogLevel(LVL_WARNING);
        }
        else if (QString::compare(logLevel, LoggerService::LOG_LEVEL_ERROR, Qt::CaseInsensitive) == 0)
        {
            this->m_pLogCommand->setLogLevel(LVL_ERROR);
        }
        else if (QString::compare(logLevel, LoggerService::LOG_LEVEL_FATAL, Qt::CaseInsensitive) == 0)
        {
            this->m_pLogCommand->setLogLevel(LVL_FATAL);
        }
        else
        {
            this->m_pLogCommand->setLogLevel(LVL_DEBUG);
        }
    }
}

void LoggerService::setLogLevel( LoggerService::LogType level )
{
    if (this->m_pLogCommand != nullptr)
    {
        this->m_pLogCommand->setLogLevel(level);
    }
}

QString LoggerService::logLevel()
{
    if (this->m_pLogCommand != nullptr)
    {
        LogType type = this->m_pLogCommand->logLevel();
        switch (type)
        {
        case LVL_DEBUG:
            return LoggerService::LOG_LEVEL_DEBUG;

        case LVL_INFO:
            return LoggerService::LOG_LEVEL_INFO;

        case LVL_WARNING:
            return LoggerService::LOG_LEVEL_WARN;

        case LVL_ERROR:
            return LoggerService::LOG_LEVEL_ERROR;

        case LVL_FATAL:
            return LoggerService::LOG_LEVEL_FATAL;

        default:
            return LoggerService::LOG_LEVEL_DEBUG;
        }
    }
    return this->m_sLogLevel;
}

void LoggerService::setLogCommand( AbstractLogCommand* pCommand )
{
    if (pCommand != nullptr)
    {
        this->m_pLogCommand = shared_ptr<AbstractLogCommand>(pCommand);
        this->m_pLogCommand->init();
        this->setLogLevel(this->m_sLogLevel);
    }
}
}
}
